#include "Worker.h"
#include "Utils.h"
#include "MysqlFunc.h"
#include "NetWork.h"

typedef struct Train_s{
    int length;
    char data[1000];
}Train;

int SplitString(char *str, char **firstPart, char **secondPart) {
    // 首先检查字符串是否为空或不存在空格
    if (str == NULL || strlen(str) == 0) {
        *firstPart = *secondPart = NULL;
        printf("路径格式非法\n");
        return 0;
    }
    
    // 遍历字符串，找到空格的位置
    char *space = strchr(str, ' ');
    
    // 如果找到空格，将字符串分割为两部分
    if (space != NULL) {
        // 分配空间给第一部分
        *firstPart = (char *)malloc(space - str + 1);
        strncpy(*firstPart, str, space - str);
        (*firstPart)[space - str] = '\0'; // 确保字符串以null终止
        // 分配空间给第二部分
        *secondPart = (char *)malloc(strlen(space + 1));
        strcpy(*secondPart, space + 1);
    } else {
        // 如果没有空格，则将整个字符串作为第一部分
        *firstPart = strdup(str);
        *secondPart = NULL;
    }
    return 0;
}

int GetFileName(char* path, char* before_slash, char* after_slash) {
    char* last_slash = strrchr(path, '/');
    // 如果找到了'/'
    if (last_slash) {
        // 复制'/'之前的内容
        strncpy(before_slash, path, last_slash - path);
        before_slash[last_slash - path] = '\0';
        // 复制'/'之后的内容
        strcpy(after_slash, last_slash + 1);
    }
    else {
        // 如果没有找到'/'，复制整个字符串
        strcpy(before_slash, path);
        before_slash[strlen(path)] = '\0';
        *after_slash = '\0';
    }
    return 0;
}
/*
==========Server Worker==========
*/

int ServerCdHandler(MYSQL *mysql_connect, const int netfd, int *pwd_file_id){
    char init[1024] = {0}; //path存储要cd到的初始路径
    char order[1024] = {0}; //order存储指令
    char result1[1024] = {0}; //result1返回指令执行结果
    //char result[1]; //返回netfd的结果，0表示成功，1表示失败
    //init = virtual path
    RecvTrain(netfd,init);

    char path[255] = {0}; //path存储要cd到的绝对路径
    SqlGetPath(mysql_connect, init, *pwd_file_id, path);
    if(strlen(path) == 0){
        printf("路径不合法！\n");
        SendTrain(netfd,"1");
        return 1;
    }
    sprintf(order,"select file_id from virtual_file_system_table where path='%s' AND tomb <> 1",path);
    SqlHandler(mysql_connect, order, rd_sql, result1);
    *pwd_file_id = atoi(result1);
    SendTrain(netfd,"0");
    return 0;
}

//fin
int ServerPwdHandler(MYSQL *mysql_connectconst, const int netfd, const int pwd_file_id){
    char sql[255] = {0};
    sprintf(sql, "select path from virtual_file_system_table where file_id = %d;", pwd_file_id);
    char result[255] = {0};
    SqlHandler(mysql_connectconst, sql, rd_sql, result);
    SendTrain(netfd, result);
    return 0;
}

//fin
int ServerLsHandler(MYSQL *mysql_connect, const int netfd, const int pwd_file_id){
    // 服务端
    // 接收虚拟路径
    char virtual_path[255] = {0};
    char result_path[255] = {0};
    RecvTrain(netfd, virtual_path);
    if (!strcmp(" ", virtual_path)){
        virtual_path[0] = '\0';
    }
    // 调用sqlgetpath，获得真实路径
    SqlGetPath(mysql_connect, virtual_path, pwd_file_id, result_path);
    if (!strcmp(result_path, "")){
        // 路径不合法 result_path == ""
        char access[10] = "1";
        SendTrain(netfd, access);
    }else{
        // 路径合法
        char access[10] = "0";
        SendTrain(netfd, access);

        // 操作数据库
        char sql_result_0[255] = {0};
        // char *sql_0 = "select file_id from virtual_file_system_table where path=result_path";
        // 获得sql的结果，存入字符串，sql_result是结果
        //   SqlHandler(mysql_connect, sql_0, rd_sql, sql_result_0);
        // 获得这个路径对应的file_id

        char sql_0[512] = {0};
        sprintf(sql_0, "select file_id from virtual_file_system_table where path ='%s';", result_path);
        SqlHandler(mysql_connect, sql_0, rd_sql, sql_result_0);
        printf("获得这个路径对应的file_id=%s\n", sql_result_0);

        // 遍历整个表的parent_id，上面的sql_result等于他是条件，找出file_name
        char sql_result_1[255] = {0};
        char sql_1[512] = {0};
        sprintf(sql_1, "select file_name from virtual_file_system_table where parent_id = '%s' AND tomb <> 1;", sql_result_0);
        SqlHandler(mysql_connect, sql_1, rd_sql, sql_result_1);

        SendTrain(netfd, sql_result_1);
    }
    return 0;
}

//fin
int ServerPutsHandler(MYSQL *mysql_connect, const int netfd, const int pwd_file_id){
    char status[2];

    //收到 path/file_name
    char net_path[255] = {0};
    RecvTrain(netfd,net_path);
    
    char filename[20] = {0};
    char per_path[1024] = {0};
    GetFileName(net_path, per_path, filename);

    char result_path[1024] = {0};
    SqlGetPath(mysql_connect, per_path, pwd_file_id, result_path);

    // 2 地址合法状态码 <<<<<<<<<<<<<<<<<<<<<
    if (result_path == NULL || strcmp(result_path,"")==0){ // 地址不合法
        printf("ERROR: Client have entered an illegal path.\n");
        // 向客户端发送状态码 1 地址不合法 <<<<<<<<<<<<<<<<<<<<<<<
        bzero(status,sizeof(status));
        strcpy(status,"1");
        SendTrain(netfd, status);
        return 0;
    }else{
        bzero(status,sizeof(status));
        strcpy(status,"0");
        SendTrain(netfd, status);
    }
    strcpy(net_path,result_path);

    // >>>>>>>>>>> 3 接收客户端打开状态
    bzero(status,sizeof(status));
    RecvTrain(netfd,status);
    if(!strcmp(status,"1")){
        printf("puts 退出.\n");
        return 0;
    }

    // 4 >>>>>>>>>>>>>>>>>>> 接收文件长度
    char filesize_char[1024] = {0};
    RecvTrain(netfd,filesize_char);
    off_t filesize = (off_t)strtol(filesize_char,NULL,10);

    // 5 >>>>>>>>>>>>>>>>>>>> md5
    char md5_value[35] = {0};
    RecvTrain(netfd,md5_value);

    // user_name
    char sql[2048];
    char get_result[1024] = {0};
    sprintf(sql, "select user_name from virtual_file_system_table where file_id = '%d';", pwd_file_id);
    SqlHandler(mysql_connect, sql, rd_sql, get_result);
    char client_username[32] = {0};
    strcpy(client_username, get_result);

    int fd = open(md5_value,O_CREAT|O_RDWR,0755);
    bzero(sql,strlen(sql));
    bzero(get_result,sizeof(get_result));
    sprintf(sql, "select file_id from virtual_file_system_table where md5 = '%s';", md5_value);
    SqlHandler(mysql_connect, sql, rd_sql, get_result);

    /*============================================================================================*/
    // get_result[strlen(get_result) - 1] = '\0';
    /*============================================================================================*/
    
    char target_path[512];
    sprintf(target_path, "%s/%s", net_path,filename); 
    
    if (strlen(get_result) != 0){ 
        bzero(status,sizeof(status));
        strcpy(status,"1");
        SendTrain(netfd, status);
        //已经确认有文件，根据path比对

        bzero(sql,strlen(sql));
        bzero(get_result,sizeof(get_result));
        sprintf(sql, "select path from virtual_file_system_table where path = '%s';",target_path);
        SqlHandler(mysql_connect, sql, rd_sql, get_result);
        if(strcmp(target_path, get_result)){
            printf("秒传\n");
            //不相同，插入表项
            bzero(sql,strlen(sql));
            bzero(get_result,strlen(get_result));
            sprintf(sql, "select file_id from virtual_file_system_table where path = %s;",net_path);
            SqlHandler(mysql_connect, sql, rd_sql, get_result);
            int parent_id = atoi(get_result);
            bzero(sql,strlen(sql));
            sprintf(sql, "insert into virtual_file_system_table(file_name, user_name, parent_id, path, type, md5, tomb) values('%s','%s', %d,'%s/%s', 1, '%s', 0);",filename,client_username,parent_id,net_path, filename, md5_value);
            SqlHandler(mysql_connect, sql, wr_sql, get_result);
        
            bzero(status,sizeof(status));
            strcpy(status,"1");
            SendTrain(netfd, status);
        }else{
            //检测文件是相同的重名文件
            bzero(sql,strlen(sql));
            bzero(get_result,sizeof(get_result));
            sprintf(sql, "select md5 from virtual_file_system_table where path = '%s';",target_path);
            SqlHandler(mysql_connect, sql, rd_sql, get_result);

            if(strcmp(md5_value,get_result)==0)
            {
                //相同，tom = 0
                bzero(sql,strlen(sql));
                bzero(get_result,strlen(get_result));
                sprintf(sql, "update virtual_file_system_table set tomb = '0' where path ='%s'",target_path);
                SqlHandler(mysql_connect, sql, wr_sql, NULL);

                bzero(status,sizeof(status));
                strcpy(status,"1");
                SendTrain(netfd, status);
                printf("秒传\n");
            }
            else{
                //返回上传失败，存在重名不同文件
                bzero(status,sizeof(status));
                strcpy(status,"0");
                SendTrain(netfd, status);
            }
        }
    }else{ 
        bzero(status,sizeof(status));
        strcpy(status,"0");
        SendTrain(netfd, status);
        
        bzero(sql,strlen(sql));
        bzero(get_result,sizeof(get_result));
        sprintf(sql, "select path from virtual_file_system_table where path = '%s';",target_path);
        SqlHandler(mysql_connect, sql, rd_sql, get_result);
        if(strcmp(target_path, get_result)==0)
        {
            bzero(status,sizeof(status));
            strcpy(status,"1");
            SendTrain(netfd, status);
        }
        else
        {
            bzero(status,sizeof(status));
            strcpy(status,"0");
            SendTrain(netfd, status);
            
            // 数据库中不存在该表项,上传文件
            // 发送偏移量
            int cursize = lseek(fd,0,SEEK_END);
            int total = filesize;
            Train train;
            bzero(&train,sizeof(train));
            train.length = sizeof(cursize);
            memcpy(train.data,&cursize,train.length);
            send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);

            int ret = 0;
            while(cursize < total)
            {
                bzero(&train,sizeof(train));
                if(total - cursize >1000)
                {
                    ret = recv(netfd,train.data,sizeof(train.data),MSG_WAITALL);
                }
                else
                {
                    ret = recv(netfd,train.data,(total - cursize),MSG_WAITALL);
                }
                write(fd,train.data,ret);
                cursize += ret;
            }

            char md5_now[33];
            ReadMd5(fd,md5_now);
            if(memcmp(md5_now,md5_value,sizeof(md5_now))==0)
            {
                bzero(status,sizeof(status));
                strcpy(status,"0");
                SendTrain(netfd, status);
            }
            else
            {
                bzero(status,sizeof(status));
                strcpy(status,"1");
                SendTrain(netfd, status);
            }
            //上传完成，插入表
            bzero(sql,strlen(sql));
            bzero(get_result,strlen(get_result));
            sprintf(sql, "select file_id from virtual_file_system_table where path = %s;",net_path);
            SqlHandler(mysql_connect, sql, rd_sql, get_result);
            int parent_id = atoi(get_result);

            bzero(sql,strlen(sql));
            sprintf(sql, "insert into virtual_file_system_table(file_name, user_name, parent_id, path, type, md5, tomb) values('%s','%s', %d,'%s/%s', 1, '%s', 0);",filename,client_username,parent_id,net_path, filename, md5_value);
            SqlHandler(mysql_connect, sql, wr_sql, get_result);
        }
    }
    close(fd);
    return 0;
}

//fin
int ServerGetsHandler(MYSQL *mysql_connect,const int net_fd,const int pwd_file_id){
    //接收网盘地址
    char net_path[255] = {0};
    RecvTrain(net_fd,net_path);
    
    //生成绝对路径（包含合法性检测）
    char ret[4] ={0};
    RecvTrain(net_fd,ret);
    if(strcmp(ret,"1")==0)
    {
        printf("客户端地址错误\n");
        return 0;
    }
    char result_path[255] = {0};
    SqlGetPath(mysql_connect,net_path,pwd_file_id,result_path);
    
    char query[512] = {0};
    if(result_path == NULL||strcmp(result_path,"")==0){
        //文件格式非法,通知client，把’1‘发过去
        bzero(ret,sizeof(ret));
        strcpy(ret,"1");
        SendTrain(net_fd,ret);
        return 0;
    }
    //合法，发送’0‘
    bzero(ret,sizeof(ret));
    ret[0] = '0';
    SendTrain(net_fd,ret);

    //查找MD5码
    char md5_buf[64] = {0};
    bzero(query,strlen(query));
    sprintf(query,"select md5 from virtual_file_system_table where path = '%s';",result_path);
    SqlHandler(mysql_connect,query,rd_sql,md5_buf);
    printf("SqlHandler result_path（md5） = %s\n",md5_buf);

    int fd = open(md5_buf,O_RDWR);

    struct stat statbuf;
    fstat(fd,&statbuf);
    off_t filesize = statbuf.st_size;
    char filesize_char[1024] = {0};
    sprintf(filesize_char,"%ld",filesize);
    printf("filesize = %s\n",filesize_char);
    SendTrain(net_fd,filesize_char);

    //发送文件
    int cursize;
    int total = filesize;
    Train train;
    bzero(&train,sizeof(train));
    recv(net_fd,&train.length,sizeof(int),MSG_WAITALL);
    recv(net_fd,train.data,train.length,MSG_WAITALL);
    memcpy(&cursize,train.data,train.length);

    int sret = 0;
    if(filesize > 100*1024*1024)
    {
        ftruncate(fd,filesize);
        char *p = (char*)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        send(net_fd,p+cursize,total-cursize,MSG_NOSIGNAL);
    }
    else
    {
        while(cursize< total)
        {
            lseek(fd,cursize,SEEK_SET);
            bzero(&train.data,sizeof(train));
            if(total - cursize > 1000)
            {
                sret = read(fd,train.data,sizeof(train.data)); 
                send(net_fd,train.data,sret,MSG_NOSIGNAL);
            }
            else
            {
                sret = read(fd,train.data,(total - cursize)); 
                send(net_fd,train.data,sret,MSG_NOSIGNAL);
            }
            cursize += sret;
        }
    }
    //发送MD5码
    SendTrain(net_fd,md5_buf);
    close(fd); 
    printf("server end\n");
    return 0;
}

//fin
int ServerRmHandler(MYSQL *mysql_connect, const int netfd, const int pwd_file_id){

    // 服务端
    // 接收虚拟路径
    char virtual_path[255] = {0};
    char result_path[255] = {0};
    printf("ServerRmHandler start!\n");
    bzero(virtual_path, 255);
    RecvTrain(netfd, virtual_path);
    if (virtual_path == NULL)    {
        // ls 命令
        printf("ls后面为空。\n");
    }else{
        // ls ./a/b 命令
        printf("虚拟路径：%s\n", virtual_path);
    }

    // 调用sqlgetpath，获得真实路径
    SqlGetPath(mysql_connect, virtual_path, pwd_file_id, result_path);
    printf("result_path=%s\n",result_path);
    if (result_path == NULL){
        // 路径不合法
        char access[10] = "1";
        SendTrain(netfd, access);
        printf("路径不合法,access=%s\n", access);
    }else{
        // 路径合法
        char access[10] = "0";
        SendTrain(netfd, access);
        printf("路径合法,access=%s\n", access);
    }
    // 操作数据库
    char sql_result_0[512] = {0};
    char sql_result_1[512] = {0};
     char sql_result_2[512] = {0};
    char sql_0[1024] = {0};
    char sql_1[1024] = {0};
     char sql_2[1024] = {0};
    // char *sql_0 = "select file_id from virtual_file_system_table where path=result_path";
    printf("sqlhandler1开始\n");
    sprintf(sql_0, "select file_id from virtual_file_system_table where path='%s';", result_path);
    SqlHandler(mysql_connect, sql_0, rd_sql, sql_result_0);
    printf("file_id=%s\n", sql_result_0);
    printf("sqlhandler1结束\n");

    printf("sqlhandler2开始\n");
    // char *sql_1 = "update virtual_file_system_table set tomb = '1' where file_id = sql_result_0";
    sprintf(sql_1, "update virtual_file_system_table set tomb = '1' where file_id ='%s';", sql_result_0);
    SqlHandler(mysql_connect, sql_1, wr_sql, sql_result_1);
    //printf("update tomb=%s\n", sql_result_1);
    printf("sqlhandler2结束\n");

   printf("sqlhandler3开始\n");
    sprintf(sql_2, "select tomb from virtual_file_system_table where file_id='%s';", sql_result_0);
    SqlHandler(mysql_connect, sql_2, rd_sql, sql_result_2);
    printf("tomb=%s\n", sql_result_2);
    printf("sqlhandler3结束\n");


    SendTrain(netfd, sql_result_2);
    printf("发送tomb!\n"); 
    return 0;
}

int ServerMkdirHandler(MYSQL *mysql_connect, const int netfd, const int pwd_file_id){
    //先考虑特殊情况：路径指示的文件存在，此时只需修改tomb即可
    char init[1024] = {0}; //init存储初始路径
    //char result[1]; //result存储给netfd发送的返回值，0表示成功，1表示失败
    RecvTrain(netfd,init);
    char path[512] = {0}; //path存储要mkdir的绝对路径
    char order[4096] = {0}; //order存储的是sql命令
    char result1[1024] = {0}; //result1存储mysql指令执行结果
    SqlGetPath(mysql_connect, init, pwd_file_id, path);
    if(strlen(path) != 0){
        memset(order,0,sizeof(order));
        sprintf(order,"update virtual_file_system_table set tomb=0 where path='%s'",path);
        SqlHandler(mysql_connect,order,wr_sql,NULL);
        SendTrain(netfd,"0");
        return 0;
    }

    //此时原mkdir的路径不存在，需要对init中存储的初始路径进行拆分
    char path1[1024] = {0};
    memset(path1,0,sizeof(path1));
    memcpy(path1,init,sizeof(init));
    char file_name[1024] = {0}; //file_name存储文件名
    int length = 0;
    int i;
    int j;
    for(i=strlen(init);i>=0;i--){
        if(path1[i] == '/'){
            length = i + 1;
            break;
        }
    }

   int idx = 0;
   for(j = length; j <= strlen(init); j++){
       file_name[idx++] = path1[j];
        path1[j] = 0;
   }

   if(length != 1 && length != 0){
       path1[length - 1] = 0;
   }
   
   //判断除去最后一段后的路径是否合法，结果放入repath中
   char repath[1024] = {0};
   SqlGetPath(mysql_connect, path1, pwd_file_id, repath);
    if(strlen(repath) == 0){
        printf("路径非法！\n");
        SendTrain(netfd,"1");
        return 1;
    }

   //file_id不用写
   //file_name为上面得到的file_name
   memset(order,0,sizeof(order));
   memset(result1,0,sizeof(result1));
   sprintf(order,"select user_name from virtual_file_system_table where path='%s'",repath);
   SqlHandler(mysql_connect, order, rd_sql, result1);
   char user_name[1024] = {0};
   memcpy(user_name,result1,strlen(result1));
   printf("user_name = %s\n",user_name);

   memset(order,0,sizeof(order));
   memset(result1,0,sizeof(result1));
   sprintf(order,"select file_id from virtual_file_system_table where path='%s'",repath);
   SqlHandler(mysql_connect, order, rd_sql, result1);
   int parent_id = atoi(result1);
   printf("parent_id = %d\n",parent_id);

   memset(path,0,sizeof(path));
   strcat(path,repath);
   strcat(path,"/");
   strcat(path,file_name);

   int type = 0;
   int tomb = 0;

   
   memset(order,0,sizeof(order));
   memset(result1,0,sizeof(result1));
   sprintf(order,"insert into virtual_file_system_table (file_name,user_name,parent_id,path,type,tomb) values ('%s','%s',%d,'%s',%d,%d);",file_name,user_name,parent_id,path,type,tomb);
   SqlHandler(mysql_connect, order, wr_sql, result1);

   SendTrain(netfd,"0");
   return 0;
}

//fin
int ServerRmdirHandler(MYSQL *mysql_connect, const int net_fd,const int pwd_file_id){
    printf("rmdir start\n");
   //接收地址
    char net_path[4096] = {0};
    RecvTrain(net_fd,net_path);
    printf("net_path = %s\n",net_path);
     
    // char result_path[4096] = {0};
    char result_path[255] = {0};
    //转换成绝对地址
    SqlGetPath(mysql_connect,net_path,pwd_file_id,result_path);
    printf("result_path = %s\n",result_path);
    
     char ret[4] = "0";
    //判断地址格式是否合法
    if(result_path == NULL){
      ret[0] = '1';
      SendTrain(net_fd,ret);
      printf("地址非法\n");
    }else{
        //合法，发送’0‘
        ret[0] = '0';
        SendTrain(net_fd,ret);
        char query[512] = {0};
        //查询表中是否有该地址对应的表项
        sprintf(query,"select path from virtual_file_system_table where path = '%s'",result_path);
        bzero(result_path,sizeof(result_path));
        SqlHandler(mysql_connect,query,rd_sql,result_path);
        printf("result_path = %s\n",result_path);
        printf("SqlHandler rd_sql\n");
        if(result_path == NULL){//result_path总是放最后查询的结果
          ret[0] = '1';
           SendTrain(net_fd,ret);//没有该目录
           printf("没有该目录\n");
        }else{
            ret[0] = '0';
            SendTrain(net_fd,ret);
            //更新表中tomb
            sprintf(query,"update virtual_file_system_table set tomb = 1 where path = '%s'",result_path);
            bzero(result_path,sizeof(result_path));
            SqlHandler(mysql_connect,query,wr_sql,result_path);
            printf("SqlHandler wr_sql\n");
            printf("rmdir end\n");
        }  
    }
    return 0;
}
/*
==========End of Server Worker=========
==========Client Worker==========
*/
int ClientCdHandler(const int sockfd, char *path){
    SendTrain(sockfd,path);
    printf("path = %s\n",path);
    char receive;
    RecvTrain(sockfd,&receive);
    if(receive == '0')
    {
        printf("cd成功\n");
    }
    else
    {
        printf("cd失败\n");
    }
    return 0;
}

int ClientPwdHandler(const int sockfd, char *path)
{
    char result[1024] = {0};
    SendTrain(sockfd, "1");
    RecvTrain(sockfd, result);
    printf("pwd: /%s\n", result);
    return 0;
}

int ClientLsHandler(const int sockfd, char *path)
{
    // 客户端
    char buf[4096] = {0};
    char name[4096] = {0};
    if (path == NULL){
        SendTrain(sockfd, " ");
    }else{
        SendTrain(sockfd, path);
    }

    // 接收路径是否合法判断
    bzero(buf, 4096);
    RecvTrain(sockfd, buf);
    char *flag = "1";
    if (strcmp(buf, flag)){
        // 路径合法,接收文件名
        bzero(name, 4096);
        RecvTrain(sockfd, name);
        // 打印ls结果
        printf("用户得到该目录下的文件名为：%s \n", name);
    }
    // 路径不合法
    else{
        printf("用户输入的路径不合法！\n");
    }
    return 0;
}
int ClientPutsHandler(const int sockfd, char *path)
{
    char status[2];

    char *firstPart = NULL;
    char *secondPart = NULL;
    SplitString(path, &firstPart, &secondPart);
    printf("第一部分： %s\n", firstPart);
    printf("第二部分： %s\n", secondPart);

    // 1 网盘路径+文件名 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    SendTrain(sockfd,secondPart);

    // 2 地址合法状态码 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    bzero(status,sizeof(status));                                           
    RecvTrain(sockfd,status);
    if(!strcmp(status,"1")){
        printf("服务端路径不合法.\n");
        printf("puts 退出.\n");
        return 0;
    }else{
        printf("服务端路径正确 Server status: %s\n",status);
    }

    // 3 发送客户端文件打开状态的状态码 >>>>>>>>>>>>>>>>>>>>>>
    int fd = open(firstPart,O_RDWR);
    if(fd == -1){
        printf("Open failed.\n");
        // >>>>>>>>>>>> 2.1 发送文件打开失败状态码 1
        bzero(status,sizeof(status));
        strcpy(status,"1");
        printf("Client status: %s\n",status);
        SendTrain(sockfd,status);
        close(fd);
        printf("puts 退出.\n");
        return 0;
    }
    // open成功,发送成功状态码 0 >>>>>>>>>>>>>>>
    printf("Open success.\n");
    bzero(status,sizeof(status));
    strcpy(status,"0");
    printf("文件路径正确 Client status: %s\n",status);
    SendTrain(sockfd,status);

    printf("=====================\n");
    // 4 发送文件长度 >>>>>>>>>>>>>>>>>>>
    struct stat statbuf;
    fstat(fd,&statbuf);
    off_t filesize = statbuf.st_size;
    char filesize_char[1024] = {0};
    sprintf(filesize_char,"%ld",filesize);
    printf("filesize = %s\n",filesize_char);
    SendTrain(sockfd,filesize_char);

    // 5 发送文件 md5 码 >>>>>>>>>>>>>>>>>
    char md5_value[33];
    ReadMd5(fd,md5_value);
    SendTrain(sockfd,md5_value);
    printf("md5: %s\n",md5_value);

    bzero(status,sizeof(status));
    RecvTrain(sockfd, status);
    if(strcmp(status, "1") == 0)
    {
        bzero(status,sizeof(status));
        RecvTrain(sockfd, status);
        if(strcmp(status, "1") == 0)
        {
            printf("秒传完成.\n");
        }
        else
        {
            printf("存在重名不同文件，上传失败\n");
        }
    }
    else{
        bzero(status,sizeof(status));
        RecvTrain(sockfd, status);
        if (strcmp(status,"0") == 0){
            printf("开始上传\n");
            int cursize;
            int total = filesize;
            Train train;
            bzero(&train,sizeof(train));
            recv(sockfd,&train.length,sizeof(int),MSG_WAITALL);
            recv(sockfd,train.data,train.length,MSG_WAITALL);
            memcpy(&cursize,train.data,train.length);

            int ret = 0;
            if(filesize > 100*1024*1024)
            {
                ftruncate(fd,filesize);
                char *p = (char*)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
                send(sockfd,p+cursize,total-cursize,MSG_NOSIGNAL);
            }
            else
            {
                while(cursize< total)
                {
                    lseek(fd,cursize,SEEK_SET);
                    bzero(&train.data,sizeof(train));
                    if(total - cursize > 1000)
                    {
                        ret = read(fd,train.data,sizeof(train.data)); 
                        send(sockfd,train.data,ret,MSG_NOSIGNAL);
                    }
                    else
                    {
                        ret = read(fd,train.data,(total - cursize)); 
                        send(sockfd,train.data,ret,MSG_NOSIGNAL);
                    }
                    cursize += ret;
                }
            }
            bzero(status,sizeof(status));
            RecvTrain(sockfd, status);
            if(strcmp(status,"0")==0)
            {
                printf("md5验证成功\n");
            }
            else
            {
                printf("md5验证失败\n");
            }
        }else{
            printf("存在重名不同文件，上传失败\n");
        }
    }
    close(fd);
    return 0;
}

int ClientGetsHandler(const int sock_fd,char *path){  
     //gets 网盘地址 本地地址
    //切分
    char *net_path = NULL;
    char *local_path = NULL;

    //对path进行切分
    SplitString(path,&net_path,&local_path);
     //发送网盘地址
    SendTrain(sock_fd,net_path);
    
    char ret[4] = "0";
    int fd = open(local_path,O_RDWR|O_CREAT| O_SYNC, 0755);
    if(fd == -1)
    {
        bzero(ret,sizeof(ret));
        strcpy(ret,"1");
        SendTrain(sock_fd,ret);
        close(fd);
        return 0;
    }
    else
    {
        bzero(ret,sizeof(ret));
        strcpy(ret,"0");
        SendTrain(sock_fd,ret);
    }
    //接收反馈结果
    bzero(ret,sizeof(ret));
    RecvTrain(sock_fd,ret);
    if(memcmp(ret,"1",1)==0){
        printf("路径格式非法\n");
    }
    else{
        char file_size_buf[255] = {0};
        RecvTrain(sock_fd, file_size_buf);
        int filesize = atoi(file_size_buf);


        //循环接收文件
        int cursize = lseek(fd,0,SEEK_END);
        int total = filesize;
        Train train;
        bzero(&train,sizeof(train));
        train.length = sizeof(cursize);
        memcpy(train.data,&cursize,train.length);
        send(sock_fd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);

        int ret = 0;
        while(cursize < total)
        {
            bzero(&train,sizeof(train));
            if(total - cursize >1000)
            {
                ret = recv(sock_fd,train.data,sizeof(train.data),MSG_WAITALL);
            }
            else
            {
                ret = recv(sock_fd,train.data,(total - cursize),MSG_WAITALL);
            }
            write(fd,train.data,ret);
            cursize += ret;
        }
        //生成MD5
        char md5_value[33] = {0};
        fsync(fd);
        ReadMd5(fd,md5_value);
        char md5[33] = {0};
        //接收MD5
        RecvTrain(sock_fd,md5);
        //生成MD5，进行对比
        printf("md5_value = %s\n",md5_value);
        printf("md5 = %s\n",md5);
        if(strcmp(md5,md5_value) != 0){
            printf("下载错误!\n");
        }else{
            printf("md5正确\n");
        }
    }
    close(fd);
    return 0;
}

int ClientRmHandler(const int sockfd, char *path){
    // 客户端
    // 发送用户路径
    char buf[4096] = {0};
    char update[4096] = {0};
    printf("ClientRmHandler start!\n");
    SendTrain(sockfd, path);
    // 接收路径是否合法判断
    bzero(buf, 4096);
    RecvTrain(sockfd, buf);
    char *flag = "1";
    printf("收到路径合法性返回值:%s\tflag=%s\n", buf, flag);
    if (strcmp(buf, flag))
    {
        // 路径合法,删除该路径下的文件
        printf("路径合法！\n");
    }
    else
    {
        // 路径不合法
        printf("路径不合法！\n");
    }
    // 接收删除是否成功的消息
    bzero(update, 4096);
    RecvTrain(sockfd, update);
    if (strcmp(update, "1"))
    {
        printf("删除失败！\n");
    }
    else
    {
        printf("删除成功！\n");
    }
    return 0;
}

int ClientMkdirHandler(const int sockfd, char *path){
    SendTrain(sockfd,path);
    char receive;
    RecvTrain(sockfd,&receive);
    if(receive == '0')
    {
        printf("mkdir成功\n");
    }
    else
    {
        printf("mkdir失败\n");
    }
    return 0;
}

int ClientRmdirHandler(const int sock_fd, char *path){
    //rmdir 地址
    //发送地址
    SendTrain(sock_fd,path);
    
    //接收网盘地址是否正确
    char ret[4] ="0";
    RecvTrain(sock_fd,ret);

    printf("ret = %s\n",ret);
    if(memcmp(ret,"1",1)==0){
        printf("非法路径格式\n");
        return 0;
    }else{
        //接收是否存在该目录
        bzero(ret,sizeof(ret));
        RecvTrain(sock_fd,ret);
        if(memcmp(ret,"1",1)==0){
            printf("不存在该目录\n");
            return 0;
        }
    }
    printf("client end\n");
    return 0;
}
/*
==========End of Client Worker==========
*/
